home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SPACE 2
/
SPACE - Library 2 - Volume 1.iso
/
utility
/
252
/
dskpcsrc
/
expressi.mod
< prev
next >
Wrap
Text File
|
1988-02-13
|
11KB
|
350 lines
IMPLEMENTATION MODULE Expression;
(*$S-,$T- turn off stack and range checking *)
IMPORT GEMAESbase;
IMPORT GEMDOS;
IMPORT M2Conversions;
IMPORT Text;
IMPORT Screen;
IMPORT Resource;
IMPORT Icon;
IMPORT Readout;
IMPORT Float;
CONST
StackSize = 30;
None = 0;
Bell = 07C;
TYPE OperatorElement = RECORD
Operand : Float.DataElement;
ValidOperand : BOOLEAN;
MathRoutine : Float.MathRoutineProc;
Precedence : CARDINAL;
END;
VAR
UpdateRegion : Screen.Box;
Stack : ARRAY [0..StackSize] OF OperatorElement;
TOS : CARDINAL; (* Top Of Stack *)
Memory : ARRAY [0..9] OF Float.DataElement;
NumberBase : INTEGER;
SpecialKey : INTEGER;
ProgramMode : BOOLEAN;
(*----------------------- LOCAL ROUTINE ----------------------------*)
PROCEDURE ClearStack;
BEGIN
Stack[0].Precedence := 0;
Float.MakeSmallLiteral ( 0, Stack[0].Operand );
Stack[0].ValidOperand := TRUE;
TOS := 0;
END ClearStack;
(*----------------------- LOCAL ROUTINE ----------------------------*)
PROCEDURE Error;
BEGIN
Float.Error := TRUE;
Readout.Write ( "Error ", UpdateRegion );
END Error;
(*----------------------- LOCAL ROUTINE ----------------------------*)
PROCEDURE DisplayTOS;
VAR
Success : BOOLEAN;
Buffer : Text.String80;
BEGIN
IF NOT Float.Error THEN
Buffer[0] := CHR (0);
Float.Image ( Stack[TOS].Operand, Buffer );
Success := Text.ConcatChar ( Buffer, ' ', Buffer );
Readout.Write ( Buffer, UpdateRegion );
END;
END DisplayTOS;
(*----------------------- LOCAL ROUTINE ----------------------------*)
PROCEDURE SetBase ( Base : INTEGER );
VAR Success : BOOLEAN;
BEGIN
Reduce ( FALSE );
IF Base = Resource.D9HEX THEN
Success := Float.SetBase ( 16, Stack[TOS].Operand );
ELSIF Base = Resource.D9DEC THEN
Success := Float.SetBase ( 10, Stack[TOS].Operand );
ELSIF Base = Resource.D9OCT THEN
Success := Float.SetBase ( 8, Stack[TOS].Operand );
ELSIF Base = Resource.D9BIN THEN
Success := Float.SetBase ( 2, Stack[TOS].Operand );
END;
IF NOT Success THEN
Error;
END;
NumberBase := Base;
END SetBase;
(*----------------------- LOCAL ROUTINE ----------------------------*)
PROCEDURE Reduce ( StopAtParenthesis : BOOLEAN );
BEGIN
LOOP
IF TOS = 0 THEN
EXIT;
ELSIF Stack[TOS].Precedence = 0 THEN
Stack[TOS-1].Operand := Stack[TOS].Operand;
Stack[TOS].ValidOperand := FALSE;
DEC (TOS);
Stack[TOS].ValidOperand := TRUE;
IF StopAtParenthesis THEN
EXIT;
END;
ELSE
IF Stack[TOS].ValidOperand AND Stack[TOS-1].ValidOperand THEN
Stack[TOS].MathRoutine (
Stack[TOS-1].Operand,
Stack[TOS].Operand,
Stack[TOS-1].Operand );
Stack[TOS].ValidOperand := FALSE;
DEC (TOS);
Stack[TOS].ValidOperand := TRUE;
IF Float.Error THEN
Error;
EXIT;
END;
ELSE
Error;
EXIT;
END;
END;
END (* LOOP *);
END Reduce;
(*----------------------- LOCAL ROUTINE ----------------------------*)
PROCEDURE ImmediateKey ( Key : INTEGER ) : BOOLEAN;
VAR KeyProcessed : BOOLEAN;
BEGIN
KeyProcessed := TRUE;
IF (Key = Resource.D9STO) OR
(Key = Resource.D9RCL) OR
(Key = Resource.D9SUM) THEN
SpecialKey := Key;
ELSE
IF (Key = Resource.D9HEX) OR
(Key = Resource.D9DEC) OR
(Key = Resource.D9OCT) OR
(Key = Resource.D9BIN) THEN
SetBase ( Key );
ELSIF Key = Resource.D9PLSMIN THEN
Float.ChangeSign ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D9CE THEN
ClearStack;
ELSIF Key = Resource.D9SIN THEN
Float.Sin ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D9COS THEN
Float.Cos ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D9TAN THEN
Float.Tan ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D9ASIN THEN
Float.ASin ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D9ACOS THEN
Float.ACos ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D9ATAN THEN
Float.ATan ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D9RECIP THEN
Float.Reciprocal ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D9SQRT THEN
Float.SquareRoot ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D9LOG THEN
Float.Log ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D9LN THEN
Float.Ln ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D91SC THEN
Float.OnesComplement ( Stack[TOS].Operand, Stack[TOS].Operand );
ELSIF Key = Resource.D9PGM THEN
IF ProgramMode THEN
ProgramMode := FALSE;
ELSE
ProgramMode := TRUE;
KeyProcessed := FALSE;
END;
ELSE
KeyProcessed := FALSE;
END;
IF Float.Error THEN
Error;
ELSIF KeyProcessed THEN
DisplayTOS;
END;
END;
RETURN (KeyProcessed);
END ImmediateKey;
(*----------------------- LOCAL ROUTINE ----------------------------*)
PROCEDURE PushReduce (
OperatorRoutine : Float.MathRoutineProc;
OperatorPrecedence : CARDINAL;
StackPrecedence : CARDINAL );
BEGIN
LOOP
IF OperatorPrecedence > Stack[TOS].Precedence THEN
INC (TOS);
IF TOS > StackSize THEN
Error;
ELSE
Stack[TOS].MathRoutine := OperatorRoutine;
Stack[TOS].Precedence := StackPrecedence;
END;
EXIT;
ELSE
IF Stack[TOS].ValidOperand AND Stack[TOS-1].ValidOperand THEN
Stack[TOS].MathRoutine (
Stack[TOS-1].Operand,
Stack[TOS].Operand,
Stack[TOS-1].Operand );
Stack[TOS].ValidOperand := FALSE;
DEC (TOS);
Stack[TOS].ValidOperand := TRUE;
DisplayTOS;
ELSE
Error;
EXIT;
END;
END;
END (* LOOP *);
END PushReduce;
(*----------------------- LOCAL ROUTINE ----------------------------*)
PROCEDURE Evaluate (
Key : INTEGER;
NumberEntered : BOOLEAN );
BEGIN
IF Key = Resource.D9DIV THEN
PushReduce ( Float.Divide, 9, 10 );
ELSIF Key = Resource.D9MULT THEN
PushReduce ( Float.Multiply, 9, 10 );
ELSIF Key = Resource.D9MINUS THEN
PushReduce ( Float.Subtract, 7, 8 );
ELSIF Key = Resource.D9PLUS THEN
PushReduce ( Float.Add, 7, 8 );
ELSIF Key = Resource.D9YTOX THEN
PushReduce ( Float.Power, 12, 11 );
ELSIF Key = Resource.D9SHF THEN
PushReduce ( Float.Shift, 5, 6 );
ELSIF Key = Resource.D9AND THEN
PushReduce ( Float.And, 3, 4 );
ELSIF Key = Resource.D9OR THEN
PushReduce ( Float.Or, 1, 2 );
ELSIF Key = Resource.D9XOR THEN
PushReduce ( Float.ExclusiveOr, 5, 6 );
ELSIF Key = Resource.D9LPAREN THEN
INC (TOS);
IF TOS > StackSize THEN
Error;
ELSE
Float.MakeSmallLiteral ( 0, Stack[TOS].Operand );
Stack[TOS].ValidOperand := TRUE;
Stack[TOS].Precedence := 0;
END;
ELSIF (Key = Resource.D9RPAREN) OR
(Key = Resource.D9EQUALS) THEN
Reduce ( Key = Resource.D9RPAREN );
DisplayTOS;
END;
END Evaluate;
(*------------------------------------------------------------------*)
PROCEDURE CompareTOS ( VAR Status : (* OUT *) CompareResult );
BEGIN
Status := CompareResult (Float.Compare ( Stack[TOS].Operand ));
END CompareTOS;
(*------------------------------------------------------------------*)
PROCEDURE ProcessKey (
Key : INTEGER;
WindowBorders : Screen.Box;
VAR Number : ARRAY OF CHAR );
VAR
Register : CARDINAL;
NumberWasEntered : BOOLEAN;
Success : BOOLEAN;
BEGIN
UpdateRegion := WindowBorders;
NumberWasEntered := (Text.Length ( Number ) <> 0);
IF Float.Error THEN
ClearStack;
Float.Error := FALSE;
END;
IF SpecialKey = None THEN
IF NumberWasEntered THEN
IF Float.Value ( Number, Stack[TOS].Operand ) THEN
Stack[TOS].ValidOperand := TRUE;
ELSE
Error;
END;
END;
IF NOT Float.Error THEN
IF NOT ImmediateKey ( Key ) THEN
Evaluate ( Key, NumberWasEntered );
END;
END;
ELSE
M2Conversions.ConvertToCardinal ( Number, Success, Register );
IF SpecialKey = Resource.D9STO THEN
Memory[Register] := Stack[TOS].Operand;
ELSIF SpecialKey = Resource.D9SUM THEN
Float.Add ( Stack[TOS].Operand, Memory[Register], Memory[Register] );
ELSIF SpecialKey = Resource.D9RCL THEN
Stack[TOS].Operand := Memory[Register];
Stack[TOS].ValidOperand := TRUE;
DisplayTOS;
END;
SpecialKey := None;
END;
END ProcessKey;
VAR
Index : CARDINAL;
Success : BOOLEAN;
BEGIN
ClearStack;
ProgramMode := FALSE;
NumberBase := Resource.D9DEC;
SpecialKey := None;
Success := Float.SetBase ( 10, Stack[TOS].Operand );
FOR Index := 0 TO 9 DO
Float.MakeSmallLiteral ( 0, Memory[Index] );
END;
END Expression.